﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace CodeAnalysisRuleCollection.Common.CSharp
{
    [ExportCodeFixProvider("StatementHasNoEffectInMaths", LanguageNames.CSharp)]
    public class StatementHasNoEffectCodeFixProvider : ICodeFixProvider
    {
        public IEnumerable<string> GetFixableDiagnosticIds()
        {
            yield return "StatementHasNoEffectInMaths";
        }

        public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken);

            var diagnosticSpan = diagnostics.First().Location.SourceSpan;

            // Find the local declaration identified by the diagnostic.
            var invocation = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<ExpressionStatementSyntax>().First();

            // return a code action that will invoke the fix.
            return new[] { CodeAction.Create("Remove statement", c => Fix(document, invocation, c)) };
        }

        private async Task<Document> Fix(Document document, ExpressionStatementSyntax invocation, CancellationToken cancellationToken)
        {
            var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken);

            var newRoot = syntaxRoot.RemoveNode(invocation, default(SyntaxRemoveOptions));

            return document.WithSyntaxRoot(newRoot);
        }
    }
}
